﻿using System;
using System.Collections;
using System.Text;
using MediaPortal.GUI.Library;
using MediaPortal.Profile;
using System.Text.RegularExpressions;

namespace MyLeech.Sites
{
  public class Binsearch : iSites
  {
    //hello.get settings.
    Settings mpSettings = new Settings(MediaPortal.Configuration.Config.GetFolder(MediaPortal.Configuration.Config.Dir.Config) + @"\MyLeech.xml");
    HTTP_Common HTTP_Common = new HTTP_Common();
    public string SiteName {
      get { return "Binsearch"; }
    }
    public string NZB_Method
    {
      get { return "POST"; }
    }
    public string NZB_Address
    {
      get { return "http://www.binsearch.info/fcgi/nzb.fcgi"; }
    }
    private string _Keyword = String.Empty;
    public string Keyword
    {
      get { return _Keyword; }
    }
    private string _REFERER = @"http://www.binsearch.info/";
    public string REFERER
    {
      get { return _REFERER; }
    }
                                 //
    private string SEARCH_URL = @"http://www.binsearch.info/index.php?max=250&font=&m=&adv_g=&adv_sort=date&postdate=&hideposter=on&hidegroup=on";
    private ArrayList Item_ID = new ArrayList();
    private ArrayList Name = new ArrayList();
    private ArrayList Size = new ArrayList();
    private ArrayList Available = new ArrayList();
    private ArrayList Total = new ArrayList();

    private string CheckboxREG = @"checkbox""\s?name=""(?<checklist_id>[\d]{8})""\s?>";
    private string NameREG = @".*?class=""s"">(?<name>.*?)</";
    private string SizeREG = @".*?size:\s(?<size>.*?),";
    private string AvailREG = @".*?available:\s.*?(?<available>\d{1,5}).*?\s/\s(?<total>\d{1,5})<";
    private string BasicREG = @"(?<checklist_id>[\d]{8}).*?class=""s""\s?>(?<name>.*?)</span";
    
    public void Do_Search(int type, GUIListControl lstItems)
    {
      lstItems.Clear(); //clear list
      mediaportalFunc Dialogs = new mediaportalFunc();
      string HTML = String.Empty;
      string START_MB = String.Empty;
      string END_MB = String.Empty;
      int START_MB_INT = 0;

      try
      {
        switch (type)
        {
          case 0: //AUTO MOVIE SEARCH
            string OPTIONS = "&adv_col=on";
            GUIPropertyManager.SetProperty("#Status","Please Select a Start Size (In MegaBytes)..."); //set status
            START_MB = Dialogs.Menu(new string[] { "300", "400", "500", "600", "700" }, "Size Start Range (MB)");
            START_MB_INT = Int32.Parse(START_MB);
            GUIPropertyManager.SetProperty("#Status", "Please Select a End Size (In MegaBytes)..."); //set status
            END_MB = Dialogs.Menu(new string[] { (START_MB_INT + 300).ToString(), (START_MB_INT + 600).ToString(), (START_MB_INT + 900).ToString(), (START_MB_INT + 1100).ToString(), (START_MB_INT + 1400).ToString() }, "Size End Range (MB)");
            SEARCH_URL = SEARCH_URL + OPTIONS + "&minsize=" + START_MB + "&maxsize=" + END_MB+"&adv_age=240&q="; //BUILD URL
            GUIPropertyManager.SetProperty("#Status", "Please Enter Keyword(s) to Search..."); //set status
            this._Keyword = Dialogs.Keyboard();
            
            string[] Filter = HTTP_Common.Filters(this.mpSettings.GetValueAsString("#Filters", "auto_movie", "DVDRIP;DVDScreener;DVD"));
            string[] Auto_Remove = HTTP_Common.Filters(this.mpSettings.GetValueAsString("#Filters", "auto_remove", "dubbed;german;french;russian;spanish"));
            for (int x = 0; x < Filter.Length; x++)
            {
              
              HTML = String.Empty;
              SEARCH_URL = SEARCH_URL + (System.Web.HttpUtility.UrlEncode(this._Keyword + " " + Filter[x]));
              HTML = this.HTTP_Common.Fetch_HTML(SEARCH_URL, this._REFERER);
              
              if(FILTER_HTML(HTML,0) == true){

                for (int i = this.Name.Count - 1; i >= 0; i--)
                {
                 if (HTTP_Common.Remove_Auto_Filter((this.Name[i].ToString()), Auto_Remove))
                  {
                    this.Item_ID.RemoveAt(i);
                    this.Name.RemoveAt(i);
                    this.Size.RemoveAt(i);
                    this.Available.RemoveAt(i);
                    this.Total.RemoveAt(i);
                  }
                }
                this.Name.Sort();
                this.Item_ID.Sort();
                this.Size.Sort();
                this.Available.Sort();
                this.Total.Sort();
                break; //end loop
              }
            }
            if (this.Item_ID.Count > 0) //if we have a result
            { //PRINT RESULTS TO LIST 
              for (int i = 0; i < this.Name.Count; i++)
              {
                Dialogs.AddItem(lstItems, this.Name[i].ToString(), this.Size[i].ToString(), this.Item_ID[i].ToString(), 1);
              }
            }
            break;
          case 1: //BASIC SEARCH TYPE 1
            //#################### SEARCH OPTIONS #########################
            bool bool_col = false;
            GUIPropertyManager.SetProperty("#Status", "Please Select a Search Option..."); //set status
            switch (Dialogs.Menu(new string[] { "Show Search Options", "Quick Search" }, "Search Option"))
            {
              case "Show Search Options":
                GUIPropertyManager.SetProperty("#Status", "Please Select The Maximum Age of Posts"); //set status
                string AGE = Dialogs.Menu(new string[] { "240", "120", "70", "21", "14", "1" }, "Maximum Article Age");
                GUIPropertyManager.SetProperty("#Status", "Please Select Whether You Want Collections..."); //set status
                string SHOW_COL = Dialogs.Menu(new string[] { "On", "Off" }, "Collections Only");
                GUIPropertyManager.SetProperty("#Status", "Please Select a Start Size (In MegaBytes)"); //set status
                START_MB = Dialogs.Menu(new string[] { "0", "250", "500", "1000", "2000","4000" }, "Size Start Range (MB)");
                START_MB_INT = Int32.Parse(START_MB);
                GUIPropertyManager.SetProperty("#Status", "Please Select a End Size (In MegaBytes)..."); //set status
                END_MB = Dialogs.Menu(new string[] { (START_MB_INT + 100).ToString(),(START_MB_INT + 250).ToString(), (START_MB_INT + 500).ToString(), (START_MB_INT + 1000).ToString(), (START_MB_INT + 2000).ToString(), (START_MB_INT + 4000).ToString() }, "Size End Range (MB)");
                this.SEARCH_URL = this.SEARCH_URL + "&adv_age=" + AGE + "&minsize=" + START_MB + "&maxsize=" + END_MB + "&adv_col=" + SHOW_COL.ToLower()+"&q=";
                if (SHOW_COL == "On") bool_col = true; //because variable show_col can't be used outside switch
                break;
              case "Quick Search":
                this.SEARCH_URL = this.SEARCH_URL + "&adv_age=240&server=&q=";
                break;
            }
            GUIPropertyManager.SetProperty("#Status", "Please Enter Keyword(s) to Search..."); //set status
            this._Keyword = Dialogs.Keyboard(); //show keyboard
            //##############################################################
            //We now have a developed search url and a keyword
            //##############################################################
            HTML = HTTP_Common.Fetch_HTML((this.SEARCH_URL+(System.Web.HttpUtility.HtmlEncode(this._Keyword))), this._REFERER);
            if (HTML.Length > 0)
            {
              int TYPE = 1;
              if (bool_col) { TYPE = 0; }
              else { TYPE = 1; }
              if (this.FILTER_HTML(HTML, TYPE)) //if we manage to extract something
              {

                for (int i = 0; i < this.Item_ID.Count; i++)
                {
                  if (bool_col) { Dialogs.AddItem(lstItems, this.Name[i].ToString(), this.Size[i].ToString(), this.Item_ID[i].ToString(), 1); }
                  else { Dialogs.AddItem(lstItems, this.Name[i].ToString(), String.Empty, this.Item_ID[i].ToString(), 1); }
                }

              }
            }
            break;
        }
        GUIPropertyManager.SetProperty("#PageTitle", "MyLeech - Binsearch Search Results"); //Set Default Title
        GUIPropertyManager.SetProperty("#Status", "Found " + this.Item_ID.Count + " Results For " + this._Keyword); //set status
      }
      catch (Exception ex)
      {
        Log.Info("Data: " + ex.Data);
        Log.Info("HelpLink: " + ex.HelpLink);
        Log.Info("InnerException: " + ex.InnerException);
        Log.Info("Message: " + ex.Message+SEARCH_URL);
        Log.Info("Source: " + ex.Source);
        Log.Info("StackTrace: " + ex.StackTrace);
        Log.Info("TargetSite: " + ex.TargetSite);
       
      }
    }
    private bool FILTER_HTML(string HTML,int TYPE){
      //********************************************
      this.Item_ID.Clear();
      this.Name.Clear();
      if (TYPE == 0)
      {
        this.Size.Clear();
        this.Available.Clear();
        this.Total.Clear();
      }
      //********************************************
      if (HTML.Contains("No results") || HTML.Length < 100) { return false; } //if "No Results" found, return
      string matchPattern = String.Empty;
      if (TYPE == 0) { matchPattern = (this.CheckboxREG + this.NameREG + this.SizeREG + this.AvailREG); } //collection search
      else { matchPattern = (this.BasicREG); } //basic search

      string Value = String.Empty; //set value for htmldecoding
      string Key = String.Empty;
      try
      {
        foreach (Hashtable grouping in
          HTTP_Common.ExtractGroupings(HTML, matchPattern, true))
        {
          foreach (DictionaryEntry DE in grouping)
          {
            if ((DE.Key.ToString()) != "0")
            {
              Value = System.Web.HttpUtility.HtmlDecode(DE.Value.ToString().Trim());
              Key = DE.Key.ToString();
              //####### KEY SWITCH ##############
              switch (Key)
              {
                case "checklist_id":
                  this.Item_ID.Add(Value);
                  break;
                case "name":
                  this.Name.Add(this.HTTP_Common.Clean_Name(Value));
                  break;
                case "size":
                  this.Size.Add(Value);
                  break;
                case "available":
                  this.Available.Add(Value);
                  break;
                case "total":
                  this.Total.Add(Value);
                  break;
              }
              //#################################
            }
            Value = String.Empty;
            Key = String.Empty;
          }//close second foreach
        }//first foreach
      }//try
      catch (Exception ex)
      {
        Log.Info("Data: " + ex.Data);
        Log.Info("HelpLink: " + ex.HelpLink);
        Log.Info("InnerException: " + ex.InnerException);
        Log.Info("Message: " + ex.Message);
        Log.Info("Source: " + ex.Source);
        Log.Info("StackTrace: " + ex.StackTrace);
        Log.Info("TargetSite: " + ex.TargetSite);
        return false;
      }
      //PRELIMINARY GARBAGE DISPOSAL
       //preliminary garbage disposal.
      if (TYPE == 0)
      {
        for (int i = this.Available.Count - 1; i >= 0; i--)
        {
          if (this.Available[i].Equals(this.Total[i])) continue;
          else
          {
            //else available is not equal to total. Remove the entry.
            this.Item_ID.RemoveAt(i); //remove entry from checklist
            this.Name.RemoveAt(i); //remove entry from name
            this.Size.RemoveAt(i); //remove from size
            this.Available.RemoveAt(i);//remove from available
            this.Total.RemoveAt(i); //remove from total
          }
        }
      }
        if (this.Item_ID.Count > 0) { return true; }
        else { return false; }
    }
   
  }
}
